﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ImageTools.Controls;

namespace ComicTool.Model
{
    public class ComicView : ViewModelBase
    {
        public ComicView()
        {
            SetupCommands();
            ScalingMode = ImageEditorScalingMode.Auto;
            Scaling = 1;
        }

        #region Commands
        public ICommand InstallCommand
        {
            get;
            private set;
        }

        public ICommand EditComicCommand
        {
            get;
            private set;
        }

        public ICommand OpenURLCommand
        {
            get;
            private set;
        }

        public ICommand OpenFileCommand
        {
            get;
            private set;
        }

        public ICommand NextCommand
        {
            get;
            private set;
        }
        public ICommand PreviousCommand
        {
            get;
            private set;
        }
        public ICommand SavePDFCommand
        {
            get;
            private set;
        }
        public ICommand SaveCBZCommand
        {
            get;
            private set;
        }
        public ICommand SaveOriginalCommand
        {
            get;
            private set;
        }

        public ICommand AutoSizeCommand
        {
            get;
            private set;
        }
        public ICommand ZoomInCommand
        {
            get;
            private set;
        }
        public ICommand ZoomOutCommand
        {
            get;
            private set;
        }
        public ICommand DeleteCurrentPageCommand
        {
            get;
            private set;
        }

        private void SetupCommands()
        {
            NextCommand = new DelegateCommand(this, Next, () =>
            {
                if (Comic == null)
                {
                    return false;
                }
                return Comic.CurrentIndex + 1 < Comic.Pages.Count;
            });
            PreviousCommand = new DelegateCommand(this, Previous, () =>
            {
                if (Comic == null)
                {
                    return false;
                }
                return Comic.CurrentIndex > 0;
            });
            SavePDFCommand = new DelegateCommand(this, () =>
            {
                ProgressText = "Exporting PDF...";
                ProgressIndeterminate = true;
                ProgressVisilibity = Visibility.Visible;
                Comic.ExportPDF(() =>
                {
                    ProgressVisilibity = Visibility.Collapsed;
                });
            }, ComicIsLoaded);
            SaveCBZCommand = new DelegateCommand(this, () =>
            {
                ProgressText = "Exporting CBZ...";
                ProgressIndeterminate = true;
                ProgressVisilibity = Visibility.Visible;
                Comic.ExportCBZ(() =>
                {
                    ProgressVisilibity = Visibility.Collapsed;
                });
            }, ComicIsLoaded);
            SaveOriginalCommand = new DelegateCommand(this, () => Comic.SaveOriginalFile(), () => ComicIsLoaded() && Comic.CanSaveOriginalFile());
            AutoSizeCommand = new DelegateCommand(this, () =>
            {
                ScalingMode = ImageEditorScalingMode.Auto;
                OnPropertyChanged("ScalingMode");
                Scaling = 1;
            }, ComicIsLoaded);

            ZoomInCommand = new DelegateCommand(this, () =>
            {
                Scaling = Math.Max(0.1, Math.Round(Scaling - 0.1, 2));
                OnPropertyChanged("Scaling");
                ScalingMode = ImageEditorScalingMode.FixedScaling;
                OnPropertyChanged("ScalingMode");
            }, ComicIsLoaded);
            ZoomOutCommand = new DelegateCommand(this, () =>
            {
                Scaling = Math.Max(0.1, Math.Round(Scaling + 0.1, 2));
                OnPropertyChanged("Scaling");
                ScalingMode = ImageEditorScalingMode.FixedScaling;
                OnPropertyChanged("ScalingMode");
            }, ComicIsLoaded);
            OpenFileCommand = new DelegateCommand(this, () =>
            {
                OpenFileDialog pfd = new OpenFileDialog();
                if (pfd.ShowDialog() ?? false)
                {
                    if (pfd.File != null)
                    {
                        Load(pfd.File);
                    }
                }
            });
            OpenURLCommand = new DelegateCommand(this, () =>
            {
                OpenURL url = new OpenURL();
                url.Show();
                url.Closed += new EventHandler(url_Closed);
            });
            EditComicCommand = new DelegateCommand(this, () =>
            {
                EditPages edit = new EditPages(this);
                edit.Show();
            }, ComicIsLoaded);
            DeleteCurrentPageCommand = new DelegateCommand(this, () =>
            {
                Comic.DeletedPages.Add(Comic.CurrentPage);
                Comic.Pages.Remove(Comic.CurrentPage);
                Comic.RefreshCurrentPage();
            }, ComicIsLoaded);
            InstallCommand = new DelegateCommand(this,
                () => Application.Current.Install(),
                () => Application.Current.InstallState == InstallState.NotInstalled);
        }


        void url_Closed(object sender, EventArgs e)
        {
            OpenURL url = sender as OpenURL;
            if (url.DialogResult ?? false)
            {
                Load(url.txtUrl.Text);
            }
        }

        private bool ComicIsLoaded()
        {
            return Comic != null;
        }

        #endregion

        public ImageEditorScalingMode ScalingMode
        {
            get;
            private set;
        }

        public double Scaling
        {
            get;
            set;
        }

        private void Next()
        {
            int index = Comic.CurrentIndex + 1;
            if (index >= Comic.Pages.Count)
            {
                index = Comic.Pages.Count;
            }
            Comic.CurrentIndex = index;
            OnPropertyChanged("Comic");
            RefreshCanExecute();
        }

        private void Previous()
        {
            int index = Comic.CurrentIndex - 1;
            if (index < 0)
            {
                index = 0;
            }
            Comic.CurrentIndex = index;
            OnPropertyChanged("Comic");
            RefreshCanExecute();
        }

        public void Load(string url)
        {
            Comic = Comic.LoadFromUri(new Uri(url));
        }

        public void Load(FileInfo info)
        {
            Comic = Comic.LoadFromFile(info);
        }

        private Visibility v = Visibility.Collapsed;
        public Visibility ProgressVisilibity
        {
            get
            {
                return v;
            }
            private set
            {
                v = value;
                OnPropertyChanged("ProgressVisilibity");
            }
        }

        private int progressPercent;
        public int ProgressPercent
        {
            get
            {
                return progressPercent;
            }
            private set
            {
                progressPercent = value;
                OnPropertyChanged("ProgressPercent");
            }
        }

        private string progressText;
        public string ProgressText
        {
            get
            {
                return progressText;
            }
            private set
            {
                progressText = value;
                OnPropertyChanged("ProgressText");
            }
        }

        private bool b;
        public bool ProgressIndeterminate
        {
            get
            {
                return b;
            }
            private set
            {
                b = value;
                OnPropertyChanged("ProgressIndeterminate");
            }
        }

        private Comic comic = null;
        public Comic Comic
        {
            get
            {
                return comic;
            }
            private set
            {
                if (comic != null)
                {
                    comic.ComicLoadingProgress -= new EventHandler<ComicLoadingProgressEventArgs>(comic_ComicLoadingProgress);
                    comic.ComicLoadingCompleted -= new EventHandler(comic_ComicLoadingCompleted);
                    comic.Dispose();
                }
                comic = value;
                comic.ComicLoadingProgress += new EventHandler<ComicLoadingProgressEventArgs>(comic_ComicLoadingProgress);
                comic.ComicLoadingCompleted += new EventHandler(comic_ComicLoadingCompleted);
                OnPropertyChanged("Comic");
            }
        }

        void comic_ComicLoadingCompleted(object sender, EventArgs e)
        {
            ProgressVisilibity = Visibility.Collapsed;
            RefreshCanExecute();
        }

        void comic_ComicLoadingProgress(object sender, ComicLoadingProgressEventArgs e)
        {
            ProgressVisilibity = Visibility.Visible;
            ProgressText = e.Text;
            if (e.Percent == null)
            {
                ProgressIndeterminate = true;
            }
            else
            {
                ProgressIndeterminate = false;
                ProgressPercent = e.Percent.Value;
            }
            RefreshCanExecute();
        }

    }
}
